<?php
require_once('./Model/PasswordHandler.php');
/**
 * Klass för hantering och kontroll av inloggningsinformation
 */
class LoginHandler extends PasswordHandler{
	private $m_db = null;
	private $m_sessionUsernameKey = 'username';
	private $m_sessionPasswordKey = 'password';
	
	public static $username = null;
	
	//sätter m_db till medskickat mysqli objekt vid instansierande av klassen
	public function __construct(Mysqli $db){
		$this->m_db = $db;
	}
	
	//returnerar resultatet av UserInfoExist
	public function IsLoggedIn($username = '', $password = ''){
		if(!empty($username) && !empty($password)){
			return $this->UserInfoExist($username, $password);	
		}
		return false;
	}
	//returnerar userId baserat på username
	public function GetUserId($username){
		$stmt = $this->m_db->prepare("SELECT userId FROM user WHERE `username` = ?;");
		$stmt->bind_param("s", $username);  
		$stmt->execute();	
		$stmt->bind_result($userId);
		
		if($stmt->fetch()){
			return $userId;
		}
		return null;	
	}
	//Returnerar innehållet för $_SESSION['username']
	public function GetSessionUsername(){
		if(isset($_SESSION[$this->m_sessionUsernameKey])){
			return $_SESSION[$this->m_sessionUsernameKey];
		}
		return null;
	}
	//Returnerar innehållet för $_SESSION['password']
	public function GetSessionPassword(){
		if(isset($_SESSION[$this->m_sessionPasswordKey])){
			return $_SESSION[$this->m_sessionPasswordKey];
		}
		return null;
	}	
	//Funktionen kontrollerar $username och $password mot en switchsats, om variablerna matchar sätts 
	//$_SESSION['username'] till $username och true returneras, i annat fall returneras false
	public function DoLogin($username, $password){
		$encryptedPassword = $this->GetEncryptedPassword($password, $username);
		
		if($this->UserInfoExist($username, $encryptedPassword)){
			$_SESSION[$this->m_sessionUsernameKey] = $username;	
			$_SESSION[$this->m_sessionPasswordKey] = $encryptedPassword;	
			return true;
		}		
		return false;
	}
	/*
	 * Genererar en unik token baserat på username
	 * om token finns uppdateras denna, annars skapas en ny som sätts i databasen
	 * token returneras sedan
	 * 
	 * @return string
	 */
	public function GenerateToken($username){
						
			$tokenCode = md5(uniqid(rand(), true));
			$usernameCode = md5($username);
			
			$stmt = $this->m_db->prepare("SELECT session FROM token WHERE `username` = ?;");
			$stmt->bind_param("s", $username);  
			$stmt->execute();
			$stmt->store_result();
			$stmt->bind_result($session);
			
			if($stmt->num_rows > 0){
				if($stmt->fetch()){
					$stmt2 = $this->m_db->prepare("UPDATE `token` SET `token` = ? WHERE `session` = ?;");
					$stmt2->bind_param("ss", $tokenCode, $session); 			
					$stmt2->execute();
					$stmt2->close();
					
					return $session.'|'.$tokenCode.'|'.$usernameCode;					
				}				
			}
			
			$sessionCode = sha1(uniqid(rand(), true));
			
			$stmt = $this->m_db->prepare("INSERT INTO token (`session`, `token`, `username`) VALUES (?, ?, ?);");
			$stmt->bind_param("sss", $sessionCode, $tokenCode, $username); 			
			$stmt->execute();
			$stmt->close();
			
			return $sessionCode.'|'.$tokenCode.'|'.$usernameCode;
	}
	/**
	 * delar upp och kontrollerar tokendelarna mot databasen,
	 * om användarnamn och session stämmer men inte token så tas den bort 
	 * och false returneras för att visa att en potensiell hijacking har skett
	 *  
	 */
	public function IsValidToken($token){
		if(strlen($token) == 106){
			
			$tokenArray = explode('|', $token);
			$session = $tokenArray[0];
			$token = $tokenArray[1];
			$username = $tokenArray[2];
			
			$stmt = $this->m_db->prepare("SELECT token, username FROM token WHERE `session` = ? AND md5(`username`) = ?;");
			$stmt->bind_param("ss", $session, $username);  
			$stmt->execute();
			$stmt->bind_result($dbToken, $dbUsername);
			
			if($stmt->fetch()){
				if($token == $dbToken){
					self::$username = $dbUsername;
					return true;
				}
				$stmt = $this->m_db->prepare("DELETE FROM `token` WHERE `session` = ? AND md5(`username`) = ?;");
				$stmt->bind_param("ss", $session, $username);  
				$stmt->execute();
				self::$username = $dbUsername;
				return false;	
			}
			return null;	
		}
		return null;
	}
	//Tar bort token från databas
	public function RemoveToken($token){
		$tokenArray = explode('|', $token);
		$username = $tokenArray[2];
		
		$stmt = $this->m_db->prepare("DELETE FROM token WHERE md5(`username`) = ?;");
		$stmt->bind_param("s", $username);  
		$stmt->execute();
	}
	//kontrollerar om användaruppgifter finns i databasen
	private function UserInfoExist($username, $password){
		
		$stmt = $this->m_db->prepare("SELECT * FROM user WHERE `username` = ? AND `password` = ? ;");
		$stmt->bind_param("ss", $username, $password);  
		$stmt->execute();
		$stmt->store_result();
		
		if($stmt->num_rows == 1){
			return true;	
		}
		return false;			
	}
	//Tar bort värdena för alla registrerade sessions variabler
	//(OBS! session_destroy kan inte användas då funktionen kallas vid flera tillfällen i Test())
	public function DoLogout(){
		session_unset();
	}
}
?>